topic "Директивы парсера Ассиста++";
[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class]
[l288;2 $$2,2#27521748481378242620020725143825:desc]
[0 $$3,0#96390100711032703541132217272105:end]
[H6;0 $$4,0#05600065144404261032431302351956:begin]
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:item]
[l288;a4;*@5;1 $$6,6#70004532496200323422659154056402:requirement]
[l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param]
[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam]
[b42;2 $$9,9#13035079074754324216151401829390:normal]
[H4;b83;*4 $$10,11#07864147445237544204411237157677:title]
[b42;a42;ph2 $$11,11#45413000475342174754091244180557:text]
[l321;t246;C@5;1 $$12,12#20902679421464641399138805415013:code]
[a83;*R6 $$13,11#31310162474203024125188417583966:caption]
[2 $$0,0#00000000000000000000000000000000:Default]
[{_}%RU-RU 
[s13; [@3 Директивы парсера Ассиста`+`+]&]
[s10; [@5 Содержание]&]
[s0; &]
[s10; [^topic`:`/`/DinrusIDE`/app`/AssistParserDirectives`_ru`-ru`#1^ 1. 
Введение]&]
[s10; [^topic`:`/`/DinrusIDE`/app`/AssistParserDirectives`_ru`-ru`#2^ 2. 
Управление исходниками, заголовочниками, 
макросами и пространствами имён]&]
[s10; [^topic`:`/`/DinrusIDE`/app`/AssistParserDirectives`_ru`-ru`#3^ 3. 
Перепись макросов, макросы пространства 
имён]&]
[s10; [^topic`:`/`/DinrusIDE`/app`/AssistParserDirectives`_ru`-ru`#4^ 4. 
Основание эвристики]&]
[s10; [^topic`:`/`/DinrusIDE`/app`/AssistParserDirectives`_ru`-ru`#5^ 5. 
Assist`+`+ C`+`+ `- директивы парсера]&]
[s0; &]
[s10;:1: [@(128.0.255) 1. Введение]&]
[s11; Парсер Ассиста`+`+ C`+`+ точно не следует 
стандартам C/C`+`+, из соображений практических
 и быстродействия. В этом документе 
приводится информация об отклонениях, 
эвристике и трюках, которые нами исполняются
 для ускорения машины и повышению 
стойкости к ошибкам.&]
[s10;:2: [@(128.0.255) 2. Управление исходниками, 
заголовочниками, макросами и пространствами
 имён]&]
[s11; Основная разница между компилятором 
C`+`+ и парсером DinrusIDE `- в том, что DinrusIDE 
обрабатывает каждый файл отдельно. 
Это абсолютное требование производительнос
ти, так как нужно составлять глобальную 
бвзу данных при редактировании файлов.&]
[s11; По этой причине определение и объявление 
должны быть в одном файле. Например&]
[s11;l288; [* File1.h]&]
[s12;l288; struct Foo `{&]
[s12;l288; &]
[s11;l288; [* File2.h]&]
[s12;l288; #include `"File1.h`"&]
[s12;l288; -|int bar;&]
[s12;l288; `};&]
[s11;  [*/ НЕ] поддерживается.&]
[s11; Правила препроцессора парсера:&]
[s11;l160;i150;O0; Все условия #if/#ifdef полагаются 
верными. Это полезно, например, при 
наличии специфично`-платформного 
кода `- парсер при этом сможет подобрать 
все варианты. Части  #else исключаются. 
Например&]
[s12;l576; #ifdef PLATFORM`_WIN32&]
[s12;l576; void CloseWindow(void `*handle) `{&]
[s12;l576; ....&]
[s12;l576; `}&]
[s12;l576; #endif&]
[s12;l576; #ifdef PLATFORM`_GTK&]
[s12;l576; void CloseWindow(void `*handle) `{&]
[s12;l576; .....&]
[s12;l576; `}&]
[s12;l576; #endif&]
[s11;l288; оба объявления CloseWindow будут в базе 
кода.&]
[s11;l160;i150;O0; При развороте макроса используется 
последняя директива #define.&]
[s12;l576; #define FOO 1&]
[s12;l576; #define FOO 2&]
[s12;l576; FOO&]
[s11;l288; Последняя строка будет развёрнута 
в `"2`".&]
[s11;l160;i150;O0; #undef отменяет последнее объявление 
одного и того же макроса, если он объявлен 
в одном и том же файле. Это применимо 
во время обработки специальных определений,
 используемых при обработке конфликтов 
имён, возникающих при подключении 
внешних библиотек:&]
[s12;l576; #define byte win32`_byte`_ // RpcNdr defines byte `-> class 
with Upp`::byte&]
[s12;l576; #define CY win32`_CY`_&]
[s12;l576; #include <objidl.h>&]
[s12;l576; #include <winnetwk.h>&]
[s12;l576; #undef byte&]
[s12;l576; #undef CY&]
[s11;l160;i150;O0; #include в файле добавляет все 
макросы, которые (рекурсивно) определены 
включаемым файлом, и все директивы 
`"using namespace`". В нём [* НЕ] используются 
определения блоков пространств имён, 
например, не поддерживается:&]
[s11;l576; [* StartNamespace.h]&]
[s12;l576; namespace MyNamespace `{&]
[s12;l576; &]
[s11;l576; [* EndNamespace.h]&]
[s12;l576; `};&]
[s12;l576; &]
[s11;l576; [* File.cpp]&]
[s12;l576; #include `"StartNamespace.h`"&]
[s12;l576; void Foo();&]
[s12;l576; #include `"EndNamespace.h`"&]
[s11;l320;~~~192; [*/ НЕ] поддерживается.&]
[s11;l160;i150;O0; Однако, если файл попадает 
в проект через #include, все макросы, определения
 using`'ов и блоков пространств имён 
включаются/используются корректно. 
Рассмотрим&]
[s11;l576; [* MasterHeader.h]&]
[s12;l576; #define FOO 1&]
[s12;l576; using namespace Bar;&]
[s12;l576; namespace Foo `{&]
[s12;l576; #include `"SubHeader.h`"&]
[s12;l576; `};&]
[s12;l576; &]
[s11;l576; [* SubHeader.h]&]
[s12;l576; &]
[s12;l576; void Fn() `{ return FOO; `}&]
[s12;l576; &]
[s11;l352; Это [* ПОДДЕРЖИВАЕТСЯ]: Fn будет в 
пространстве имён Foo, и будет возвращать 
1.&]
[s10;:3: [@(128.0.255) 3. Перепись макросов, макросы 
пространства имён]&]
[s11; Можно указать DinrusIDE на перепись определения
 определённых макросов в специальных 
файлах .defs. Один глобальный файл.defs 
находится в конфигурации DinrusIDE и доступен 
через пакет `"<meta>`". Также файлы .defs 
можно помещать в пакеты. Если макрос 
определён в файлах .defs, он переписывает 
все случаи этого идентификатора во 
всех классах.&]
[s11; Заметьте, что после изменения файла 
.defs, необходимо повторить сканирование 
кода.&]
[s11; Файлы .defs также используются для 
отмены одной проблемы, у которой нет 
лучшего решения в этом фреймворке. 
Рассмотрим&]
[s11; File.h&]
[s12; #include `"Core.h`"&]
[s12; NAMESPACE`_UPP&]
[s12; #include `"subheader.h`"&]
[s12; END`_UPP`_NAMESPACE&]
[s12; &]
[s11; где NAMESPACE`_UPP и END`_UPP`_NAMESPACE определены 
где`-то в Core.h как&]
[s12; &]
[s12; #define NAMESPACE`_UPP namespace Upp `{&]
[s12; #define END`_UPP`_NAMESPACE `};&]
[s12; &]
[s11; К несчастью, в логике парсера мы не 
обнаружили быстрого способа обнаружения 
и разрешения подобной ситуации (нам 
не известно значение NAMESPACE`_UPP/END`_UPP`_NAMESPACE 
при извлечении макроса из File.h). Решение 
простое `- поместить эти #defines в файл 
.defs. Это решает проблему, поскольку 
такие макросы обнаруживаются специальным 
кодом и используются при обработке 
File.h.&]
[s10;:4: [@(128.0.255) 4. Основание эвристики]&]
[s11; Неплохая идея `- повысить устойчивость 
парсера к багам, включая код, который 
ему не понятен. По этой причине парсер 
использует нечто странное `- очень 
действенную и простую эвристику: Если 
строчка начинается (по символу нуль) 
с идентификатора, за которым не следует 
единичный символ `':`' (чтобы исключить 
лейблы),то это определение на `'глобальном`' 
уровне. Рассмотрим&]
[s12; void Fn1() `{&]
[s12; -|for(int i `= 0; i < 10; i`+`+) `{&]
[s12; -|-|Cout() << i;&]
[s12; `}&]
[s12; &]
[s12; void Fn2() `{&]
[s12; `}&]
[s12; &]
[s11; Отсутствует `'`}`' в Fn1, от чего парсер 
может потерять остаток файла (так 
как всё будет пониматься как часть 
тела Fn1). Однако определение Fn2 вызывает 
основную эвристику и парсинг повторяется 
с этой точки, не пропуская Fn2.&]
[s10;:5: [@(128.0.255) 5. Assist`+`+ C`+`+ `- директивы парсера]&]
[s11; Ассист поддерживает простые директивы, 
которые передаются через комменты 
`'//`', и могут использоваться в тех 
случаях, когда оригинальный код запутанный:&]
[ {{3850:6150 [s12;l32; [*+75 //`$`-]]
:: [s11; Код после этой директивы [*/ не] передаётся 
парсеру.]
:: [s12;l32; [*+75 //`$`+]]
:: [s11; Код после этой директивы передаётся 
парсеру (останавливает [*C@5+75 //`$`-]).]
:: [s12;l32; [*+75 //`$_][*/+75 code]&]
[s12;l32; [A@0+75 пример:][*+75  //`$ void Foo(Bar`&)]]
:: [s11; Код передаётся парсеру (добавляет 
код, не являющийся частью скомпилированных 
исходников)]}}&]
[s0; ]]